// Copyright (c) 2008-2010, Arne Claus
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
// following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice, this list of conditions and the following 
//   disclaimer.
// - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
//   disclaimer in the documentation and/or other materials provided with the distribution.
// - Neither the name Arne Claus nor the names of any contributors may be used to endorse or promote products
//   derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef __INCLUDED_CBL_POOLMANAGER_H__
#define __INCLUDED_CBL_POOLMANAGER_H__

#include "CBL_Defines.h"
#include "CBL_Singleton.h"
#include "CBL_FreeList.h"
#include "CBL_Locks.h"
#include <vector>

CB_SUBNAMESPACE_START(Memory)

//! \brief	This class can be used to manage multiple freelists. This manager will automaticaly be used when
//!			using PooledObjects. You can however use this to manage your own freelists, too. You will have
//!			a performance overhead for finding a list for the correct size (so don't use this manager if you're
//!			performance critical), but you can easily safe memory with this manager as there will not be multiple
//!			lists for identical object sizes.

class CPoolManager : public CSingleton<CPoolManager>
{
public:
    
    template <typename TClassName>
    inline TClassName* Allocate();
    
    //! \brief	Just allocates memory without calling the constructor.
    //!			Use only if you know what you're doing.
    inline void* Allocate(size_t _Size);
    
    template <typename TClassName>
    inline void Free(TClassName* _pObject);
    
    //! \brief	Just frees memory without calling the destructor.
    //!			Use only if you know what you're doing.
    inline void Free(void* _pObject, size_t _Size);
    
    //! \brief	Use this function if you want to add a Freelist for a specific size
    //!			with non-default settings.
    BASELIB_API void AddFreeList(CFreeList* _pList);
    
private:
    
    static const size_t SizeBucketGranularity = 128; // Must be power of 2
    
    CFreeList* FindListForSize(uint32 _BlockSize);
	CFreeList* GetSlot(uint32 _BlockSize) { return GetSlot(IndexForSize(_BlockSize), _BlockSize); }
	CFreeList* GetSlot(uint32 _Index, uint32 _BlockSize);
    
    uint32 IndexForSize(uint32 _BlockSize) const { return _BlockSize & (SizeBucketGranularity-1); }
    
private:
    
    CBL_SINGLETON_PRIVATE(CPoolManager);
    
    BASELIB_API CPoolManager();
    BASELIB_API ~CPoolManager();
    
    CPoolManager(const CPoolManager&);				// Not implemented on purpose
    CPoolManager& operator = (const CPoolManager&);	// Not implemented on purpose
    
private:
    
    typedef std::vector<CFreeList*> CBucketVector;
    
    CBucketVector m_SizeBuckets[SizeBucketGranularity];
	Cpu::CRWLock  m_AllocatorLock;
};

#include "CBL_PoolManager.hpp"

CB_SUBNAMESPACE_END

#endif